package com.lanxiao.cloud.modules.oauth.application.assembler;

import com.lanxiao.cloud.common.core.dto.UserBaseDto;
import com.lanxiao.cloud.common.core.utils.TreeUtils;
import com.lanxiao.cloud.common.fill.FillAppointment;
import com.lanxiao.cloud.common.fill.FillHandle;
import com.lanxiao.cloud.common.fill.FillHandleFactory;
import com.lanxiao.cloud.common.fill.FillType;
import com.lanxiao.cloud.modules.oauth.application.dto.PermissionCmdAdd;
import com.lanxiao.cloud.modules.oauth.application.dto.PermissionCmdUpdate;
import com.lanxiao.cloud.modules.oauth.application.dto.PermissionDto;
import com.lanxiao.cloud.modules.oauth.application.dto.PermissionTreeDto;
import com.lanxiao.cloud.modules.oauth.application.dto.RolePermissionDto;
import com.lanxiao.cloud.modules.oauth.application.dto.RolePermissionResultDto;
import com.lanxiao.cloud.modules.oauth.application.dto.RouteDto;
import com.lanxiao.cloud.modules.oauth.domain.model.Permission;
import com.lanxiao.cloud.modules.oauth.infrastructure.enums.TypeEnum;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import org.springframework.stereotype.Component;

/**
 * @author ：qiaoliang
 * @date ：2021-09-15
 */
@Component
public class PermissionAssembler {

  private final FillHandleFactory fillHandleFactory;

  public PermissionAssembler(FillHandleFactory fillHandleFactory) {
    this.fillHandleFactory = fillHandleFactory;
  }

  public List<PermissionTreeDto> toPermissionTreeDto(List<Permission> list) {
    final List<PermissionTreeDto> permissionTreeDtos = PermissionConverter.INSTANCE.toPermissionTreeDto(
        list);
    List<FillAppointment<PermissionTreeDto, UserBaseDto<Long>>> fillAppointments = new ArrayList<>();
    List<Function<PermissionTreeDto,Long>> functions = new ArrayList<>();
    fillAppointments.add(PermissionTreeDto::setCreateUser);
    fillAppointments.add(PermissionTreeDto::setUpdateUser);
    functions.add(o->o.getCreateUser().getId());
    functions.add(o->o.getUpdateUser().getId());
    fillHandleFactory.fill(permissionTreeDtos, new FillHandle<>(FillType.USER_INFO, fillAppointments, functions));
    return TreeUtils.buildByRecursive(permissionTreeDtos, 1L);
  }

  public List<PermissionDto> toPermissionParentDto(List<Permission> list) {
    return PermissionConverter.INSTANCE.toPermissionParentDto(list);
  }

  public RolePermissionResultDto toRolePermissionDto(List<Permission> list, List<Long> ids) {
    final List<RolePermissionDto> rolePermissionDtos = PermissionConverter.INSTANCE.toRolePermissionDto(
        list);
    return new RolePermissionResultDto(ids, TreeUtils.buildByRecursive(rolePermissionDtos, 1L));
  }

  public List<RouteDto> toRouteDto(List<Permission> list) {
    return TreeUtils.buildByRecursive(PermissionConverter.INSTANCE.toRouteDto(list), 1L);
  }

  public Permission toPermission(PermissionCmdAdd cmdAdd) {
    return PermissionConverter.INSTANCE.toPermission(cmdAdd);
  }

  public Permission toPermission(Long id, PermissionCmdUpdate cmdUpdate) {
    final Permission permission = PermissionConverter.INSTANCE.toPermission(cmdUpdate);
    permission.setId(id);
    return permission;
  }

  @Mapper
  public interface PermissionConverter {

    PermissionConverter INSTANCE = Mappers.getMapper(PermissionConverter.class);

    @Mappings({
        @Mapping(source = "createBy", target = "createUser.id"),
        @Mapping(source = "updateBy",target = "updateUser.id")
    })
    PermissionTreeDto toPermissionTreeDto(Permission permission);
    List<PermissionTreeDto> toPermissionTreeDto(List<Permission> permission);

    Permission toPermission(PermissionCmdAdd cmdAdd);
    Permission toPermission(PermissionCmdUpdate cmdUpdate);

    RolePermissionDto toRolePermissionDto(Permission permission);
    List<RolePermissionDto> toRolePermissionDto(List<Permission> permission);

    PermissionDto toPermissionParentDto(Permission permission);
    List<PermissionDto> toPermissionParentDto(List<Permission> permission);

    @Mappings({
        @Mapping(source = "title", target = "meta.title"),
        @Mapping(source = "icon",target = "meta.icon")
    })
    RouteDto toRouteDto(Permission permission);
    List<RouteDto> toRouteDto(List<Permission> permission);

  }

}
